#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

typedef uint64_t u64;
typedef int64_t i64;
typedef uint32_t u32;
typedef int32_t i32;
typedef uint8_t u8;
typedef int8_t i8;

struct gchdr
{
  u32 len;
  bool mark;
};

struct freelist
{
  u8 *data;
  u32 len;
  struct freelist *next;
};

enum
{
  VMAX = 65536,
};

struct runtime
{
  u8 raw[VMAX];
  struct freelist *free;
};

[[noreturn]] void
panic (char const *message)
{
  fprintf (stderr, "PANIC: %s", message);
  fflush (stderr);
  abort ();
}

// 申请长度是 len 字节的内存，调用者保证 len 的头部是 struct gchdr。
void *
gc_allocate (struct runtime *rt, u32 len)
{
  if (len < sizeof (struct gchdr))
    panic ("allocate less then size of gc header");

  for (struct freelist **it = &rt->free; (*it) != NULL; it = &(*it)->next)
    {
      if ((*it)->len < len)
        continue;

      void *data = (*it)->data;

      struct freelist *newfree
          = (struct freelist *)malloc (sizeof (struct freelist));

      newfree->data = (*it)->data + len;
      newfree->len = (*it)->len - len;
      newfree->next = (*it)->next;

      *it = newfree;

      return data;
    }

  panic ("out of memory");
}

enum vtype
{
  VT_NIL,
  VT_BOOL,
  VT_I64,
  VT_U64,
  VT_I32,
  VT_U32,
  VT_LIST,
};

struct vlist;

struct val
{
  struct gchdr hdr;
  enum vtype type;

  union
  {
    bool b;
    i64 i64;
    u64 u64;
    i32 i32;
    u32 u32;
    struct vlist *list;
  } via;
};

struct vlist
{
  struct gchdr hdr;
  struct val v;
  struct vlist *next;
};

int
main ()
{
  struct runtime *rt = (struct runtime *)malloc (sizeof (struct runtime));

  rt->free = (struct freelist *)malloc (sizeof (struct freelist));

  // Put all of rt->raw in free list.
  rt->free->data = rt->raw;
  rt->free->len = VMAX;

  // No next node.
  rt->free->next = NULL;

  free (rt);
  return 0;
}
